/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.usc.cs576.lib.mediaObject;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.DataLine.Info;

/**
 * Basic object for media object
 * @author haoxu
 */
public class Audio {// implements MediaObject {

    private String filepath;
    private String filename;
    SourceDataLine dataLine;
    private InputStream waveStream;
    AudioInputStream audioInputStream;
    private final int EXTERNAL_BUFFER_SIZE = 524288;
    boolean statisReady;
    int totalSize;
    int currentSize;
    int pos;
    Clip clip;
     Info info;
//    public String getName(){
//    return "s";
//            }

    public Audio() {
        SourceDataLine dataLine = null;
        statisReady = false;
        totalSize = -1;
        currentSize = -1;
    }

    public Audio(String filepath) {
        // SourceDataLine dataLine = null;
        statisReady = false;
        totalSize = -1;
        currentSize = -1;
        this.filepath = filepath;
    }

    public void load() {


        //   public void show() {
        {
            int stop = 0;
            try {
                if (filepath == null) {
                    System.err.print(this);
                }
                waveStream = new FileInputStream(filepath);
                audioInputStream = AudioSystem.getAudioInputStream(this.waveStream);

                AudioFormat audioFormat = audioInputStream.getFormat();
                System.out.println(audioFormat);
                //Info info = new Info(SourceDataLine.class, audioFormat);
                int num = 2;
                Info info = new DataLine.Info(
                        Clip.class, audioFormat,
                        ((int) audioFormat.getFrameSize() * (int) audioInputStream.getFrameLength()));//;audioFormat.getFrameSize()));
                //Create a line info object

                //  dataline = (SourceDataLine) AudioSystem.getLine(info);
                clip = (Clip) AudioSystem.getLine(info);
                clip.open(audioInputStream);
                //  dataline.open(audioFormat, this.EXTERNAL_BUFFER_SIZE);

            } catch (LineUnavailableException ex) {
                Logger.getLogger(Audio.class.getName()).log(Level.SEVERE, null, ex);
            } catch (UnsupportedAudioFileException ex) {
                Logger.getLogger(Audio.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(Audio.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }

    public void load2() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        if (filepath == null) {
            System.err.print(this);
        }
        waveStream = new FileInputStream(filepath);
        audioInputStream = AudioSystem.getAudioInputStream(this.waveStream);
// Obtain the information about the AudioInputStream
        AudioFormat audioFormat = audioInputStream.getFormat();
        System.out.println(audioFormat);
        Info info = new Info(SourceDataLine.class, audioFormat);

        // opens the audio channel
        dataLine = null;
        dataLine = (SourceDataLine) AudioSystem.getLine(info);
        dataLine.open(audioFormat, this.EXTERNAL_BUFFER_SIZE);
    }

    public void show2() throws IOException {
        if (thread == null) {
            thread = new PlayAudioThread();
            thread.start();
        }else{
            thread.resume();
        }
    }

    public void show() {
        pos = clip.getFramePosition();
        System.out.println(clip.getFrameLength());
        System.out.println("pos: " + pos);
        if (clip.getFramePosition() == clip.getFrameLength()) {
            set();
        }
        clip.start();
//        pos = clip.getFramePosition();
        System.out.println("pos: " + pos);
//        System.out.println(clip.getFrameLength());
        //clip.setFramePosition(0);
    }

    public int getPos() {
        return clip.getFramePosition();
    }
 public int getPos2() {
        return dataLine.getFramePosition();
    }
    public void set() {
        clip.setFramePosition(0);
    }

    public void pause2() {
        if (thread != null) {
           // System.out.println("222222222");
            thread.suspend();
        }
    }

    public void stop2() {
        if (thread != null) {
            System.out.println("Stop!!!!!!!!");
           thread.stop();
           
        }
    }

    public void resume() {
        if (thread != null) {
            thread.resume();
        }
    }

    public void pause() {
        clip.stop();
    }

    public void stop() {
        clip.stop();
        clip.setFramePosition(0);

    }

    public int getf() {
        return clip.getFrameLength();
    }
 public int getf2() {
        return dataLine.getBufferSize();
    // return info.
    }
    public String getFilename() {
        return filename;
    }

    public void setFilename(String filename) {
        this.filename = filename;
    }

    public String getFilepath() {
        return filepath;
    }

    public void setFilepath(String filepath) {
        this.filepath = filepath;
    }

    public InputStream getWaveStream() {
        return waveStream;
    }

    public void setWaveStream(InputStream waveStream) {
        this.waveStream = waveStream;
    }
//    public static void  main(String args[]){
//        String add="D:\\subject\\multimedia\\gollum_22050hz_16bit_mono_1min.wav";
//        Audio newAudio=new Audio(add);
//        System.out.println("hello!!!!!!!!!!");
//        newAudio.load();
//         System.out.println("world!!!!!!!!!!");
//        newAudio.show();
//        System.out.println("test!!!!!!!!!!");
//}

    public static void main(String args[]) {
        try {
            Audio au = new Audio("C:\\Users\\Jane\\Documents\\2nd_sample\\2nd_sample\\interview_22050_16.wav");
            au.load2();
            au.show2();
            Thread.sleep(2000);
            au.pause2();
            Thread.sleep(2000);
            au.resume();
        } catch (InterruptedException ex) {
            Logger.getLogger(Audio.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedAudioFileException ex) {
            Logger.getLogger(Audio.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Audio.class.getName()).log(Level.SEVERE, null, ex);
        } catch (LineUnavailableException ex) {
            Logger.getLogger(Audio.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
    private PlayAudioThread thread;

    class PlayAudioThread extends Thread {

        @Override
        public void run() {
            dataLine.start();

            int readBytes = 0;
            byte[] audioBuffer = new byte[EXTERNAL_BUFFER_SIZE];
            try {
                while (readBytes != -1) {
                    readBytes = audioInputStream.read(audioBuffer, 0,
                            audioBuffer.length);
                    if (readBytes >= 0) {
//                        if(stopPlay){
//                            break;
//                        }
                        dataLine.write(audioBuffer, 0, readBytes);
                    }
                }
            } catch (IOException e1) {
                // throw new PlayWaveException(e1);
            } finally {
                // plays what's left and and closes the audioChannel
                dataLine.drain();
                dataLine.close();
            }
        }
    }
}
